// 定义农历数据表
const lunarInfo = [
  0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
  0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,
  0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
  0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
  0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,
  0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
  0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,
  0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
  0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,
  0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
  0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,
  0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,
  0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,
  0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,
  0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0
];

// 公历日期转农历日期
function lunarCalendar(year, month, day) {
  if (year < 1900 || year > 2100) {
    return '无法转换';
  }

  // 计算农历日期的基准日期
  const baseDate = new Date(1900, 0, 31);
  const baseLunarYear = 1900;
  const baseLunarMonth = 11;
  const baseLunarDay = 11;
  const offset = Math.floor((new Date(year, month - 1, day) - baseDate) / 86400000);

  // 计算农历年份
  let lunarYear = baseLunarYear;
  let daysOfYear = 0;
  while (lunarYear < 2100 && offset >= 0) {
    daysOfYear = lunarYearDays(lunarYear);
    offset -= daysOfYear;
    lunarYear++;
  }
  if (offset < 0) {
    offset += daysOfYear;
    lunarYear--;
  }

  // 计算农历月份和日期
  let lunarMonth = baseLunarMonth;
  let leapMonth = leapMonthOfYear(lunarYear);
  let isLeapMonth = false;
  let daysOfMonth = 0;

  for (let i = 1; i <= 12; i++) {
    if (lunarMonth === leapMonth && !isLeapMonth) {
      isLeapMonth = true;
      i--;
      daysOfMonth = leapDays(lunarYear);
    } else {
      daysOfMonth = monthDays(lunarYear, lunarMonth);
    }

    offset -= daysOfMonth;
    if (offset < 0) {
      offset += daysOfMonth;
      lunarMonth = i;
      break;
    }

    if (isLeapMonth) {
      isLeapMonth = false;
    } else {
      lunarMonth++;
    }
  }

  // 计算农历日期
  const lunarDay = baseLunarDay + offset;

  return {
    lunarYear,
    lunarMonth,
    lunarDay
  };
}

// 计算农历年份的天数
function lunarYearDays(year) {
  let sum = 348;
  for (let i = 0x8000; i > 0x8; i >>= 1) {
    sum += (lunarInfo[year - 1900] & i) ? 1 : 0;
  }
  return sum + leapDays(year);
}

// 计算农历闰月的天数
function leapDays(year) {
  if (leapMonthOfYear(year)) {
    return (lunarInfo[year - 1900] & 0x10000) ? 30 : 29;
  } else {
    return 0;
  }
}

// 计算农历闰月的月份
function leapMonthOfYear(year) {
  return lunarInfo[year - 1900] & 0xf;
}

// 计算农历某年某月的天数
function monthDays(year, month) {
  return (lunarInfo[year - 1900] & (0x10000 >> month)) ? 30 : 29;
}

// 示例使用
const date = new Date(2023, 10, 1); // 公历日期，月份从0开始，这里表示2023年11月1日
const lunarDate = lunarCalendar(date.getFullYear(), date.getMonth() + 1, date.getDate());
console.log(`农历日期：${lunarDate.lunarYear}年${lunarDate.lunarMonth}月${lunarDate.lunarDay}日`);
